package cn.tedu.csmall.passport.filter;

import cn.tedu.csmall.passport.web.JsonResult;
import cn.tedu.csmall.passport.web.ServiceCode;
import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>处理JWT的过滤器</p>
 *
 * <p>此过滤器将尝试获取请求中的JWT数据，如果存在有效数据，将尝试解析，</p>
 * <p>然后，将解析得到的结果存入到Spring Security的上下文中，</p>
 * <p>以至于Spring Security框架中的其它组件能够从上下文中获取到用户的信息，</p>
 * <p>从而完成后续的授权访问。</p>
 */
@Slf4j
@Component
public class JwtAuthorizationFilter extends OncePerRequestFilter {

    public JwtAuthorizationFilter() {
        log.debug("创建处理JWT的过滤器对象：JwtAuthorizationFilter");
    }

    // 最终，过滤器可以选择“阻止”或“放行”
    // 如果选择“阻止”，则后续的所有组件都不会被执行
    // 如果选择“放行”，会执行“过滤器链”中剩余的部分，甚至继续向后执行到控制器等组件
    @Override
    protected void doFilterInternal(
            HttpServletRequest request,
            HttpServletResponse response,
            FilterChain filterChain) throws ServletException, IOException {
        // 此方法是任何请求都会执行的方法
        log.debug("执行JwtAuthorizationFilter");

        // 清除Security的上下文
        // 如果不清除，只要此前存入过信息，即使后续不携带JWT，上下文中的登录信息依然存在
        SecurityContextHolder.clearContext();

        // 从请求头中获取JWT
        String jwt = request.getHeader("Authorization");
        log.debug("从请求头中获取的JWT数据：{}", jwt);

        // 先判断是否获取到了有效的JWT数据，如果无JWT数据，直接放行
        if (!StringUtils.hasText(jwt)) {
            log.debug("请求头中的JWT数据是无效的，直接放行");
            filterChain.doFilter(request, response);
            return;
        }
        Claims claims = Jwts.parser().setSigningKey("sdfdsgsdgdsgdsgdsfsdfsdag32wrw")
                .parseClaimsJws(jwt).getBody();
        Object username = claims.get("username");
        log.debug("从JWT中解析得到的用户名:{}",username);
        Object authoritiesString = claims.get("authorities");
        log.debug("从JWT中解析得到的权限列表的字符串:{}",authoritiesString);

        GrantedAuthority authority = new SimpleGrantedAuthority("1");
        List<SimpleGrantedAuthority> authorities =
                JSON.parseArray(authoritiesString.toString(),SimpleGrantedAuthority.class);


        Authentication authentication = new UsernamePasswordAuthenticationToken(username,null,authorities);
        SecurityContext securityContext = SecurityContextHolder.getContext();
        securityContext.setAuthentication(authentication);
        // 以下代码将执行“放行”
        filterChain.doFilter(request, response);
    }

}
